package com.gr3g.dev.draw;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;
import javax.json.JsonWriter;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import com.gr3g.dev.learndraw.model.Dessin;
import com.gr3g.dev.learndraw.model.Etape;
import com.gr3g.dev.learndraw.model.IPath;
import com.gr3g.dev.learndraw.model.draw.Arc;
import com.gr3g.dev.learndraw.model.draw.Circle;
import com.gr3g.dev.learndraw.model.draw.Line;

/** @author Gregory Tardivel */
public final class PanelDraw extends JPanel {

    /** Numéro de série. */
    private static final long serialVersionUID = 4065265414330344437L;

    /** Modele. */
    private Dessin modele;
    /** Etape en cours. */
    private IPath draw;

    private final Map<IPath, Boolean> showPaths;
    private final Map<Etape, Boolean> showEtapes;

    private final JLabel positionX;
    private final JLabel positionY;

    private final TreeDraw tree;
    private boolean actif;

    /** Constructeur.
     * @param pTree TreeDraw
     * @param posX position X
     * @param posY position Y */
    public PanelDraw(final TreeDraw pTree, final JLabel posX, final JLabel posY) {
        super();
        this.tree = pTree;
        this.positionX = posX;
        this.positionY = posY;
        this.setSize(640, 400);
        this.modele = new Dessin();
        this.showPaths = new HashMap<IPath, Boolean>();
        this.showEtapes = new HashMap<Etape, Boolean>();
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(final MouseEvent pEvent) {
                if (PanelDraw.this.draw != null) {
                    if (PanelDraw.this.draw instanceof Line) {
                        final Line line = (Line) PanelDraw.this.draw;
                        line.setX1((int) (pEvent.getX() / 6.4));
                        line.setY1(pEvent.getY() / 4);
                    } else if (PanelDraw.this.draw instanceof Circle) {
                        final Circle circle = (Circle) PanelDraw.this.draw;
                        circle.setX((int) (pEvent.getX() / 6.4));
                        circle.setY(pEvent.getY() / 4);
                    } else if (PanelDraw.this.draw instanceof Arc) {
                        final Arc arc = (Arc) PanelDraw.this.draw;
                        arc.setLeft((int) (pEvent.getX() / 6.4));
                        arc.setTop(pEvent.getY() / 4);
                    }
                    PanelDraw.this.actif = true;
                }
                PanelDraw.this.repaint();
            }

            @Override
            public void mouseReleased(final MouseEvent pEvent) {
                PanelDraw.this.actif = false;
                PanelDraw.this.repaint();
                PanelDraw.this.refreshModel();
            }
        });
        this.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseMoved(final MouseEvent pEvent) {
                PanelDraw.this.positionX.setText(String.valueOf((int) (pEvent
                        .getX() / 6.4)));
                PanelDraw.this.positionY.setText(String
                        .valueOf(pEvent.getY() / 4));
            }

            @Override
            public void mouseDragged(final MouseEvent pEvent) {
                if (PanelDraw.this.draw != null && PanelDraw.this.actif) {
                    if (PanelDraw.this.draw instanceof Line) {
                        final Line line = (Line) PanelDraw.this.draw;
                        line.setX2((int) (pEvent.getX() / 6.4));
                        line.setY2(pEvent.getY() / 4);
                    } else if (PanelDraw.this.draw instanceof Circle) {
                        final Circle circle = (Circle) PanelDraw.this.draw;
                        final int x = (int) (pEvent.getX() / 6.4);
                        circle.setRadius(x - circle.getX());
                    } else if (PanelDraw.this.draw instanceof Arc) {
                        final Arc arc = (Arc) PanelDraw.this.draw;
                        arc.setRight((int) (pEvent.getX() / 6.4));
                        arc.setBottom(pEvent.getY() / 4);
                    }
                }
                PanelDraw.this.positionX.setText(String.valueOf((int) (pEvent
                        .getX() / 6.4)));
                PanelDraw.this.positionY.setText(String
                        .valueOf(pEvent.getY() / 4));
                PanelDraw.this.repaint();
            }
        });
    }

    /** @return the modele */
    public Dessin getModele() {
        return this.modele;
    }

    /** {@inheritDoc} */
    @Override
    public void paint(final Graphics pGraph) {
        final Graphics2D draw = (Graphics2D) pGraph;
        draw.setStroke(new BasicStroke(2));
        pGraph.setColor(Color.WHITE);
        pGraph.fillRect(0, 0, 640, 400);
        pGraph.setColor(Color.BLUE);
        pGraph.drawRect(64, 40, 512, 320);

        pGraph.setColor(Color.LIGHT_GRAY);
        for (final Etape etape : this.modele.getEtapes()) {
            if (Boolean.TRUE.equals(this.showEtapes.get(etape))) {
                for (final IPath path : etape.getPaths()) {
                    if (Boolean.TRUE.equals(this.showPaths.get(path))) {
                        if (path instanceof Line) {
                            final Line line = (Line) path;
                            pGraph.drawLine((int) (line.getX1() * 6.4), line
                                    .getY1() * 4, (int) (line.getX2() * 6.4),
                                    line.getY2() * 4);
                        } else if (path instanceof Circle) {
                            final Circle circle = (Circle) path;
                            final int radius = (int) (circle.getRadius() * 6.4);
                            if (circle.isFilled()) {
                                pGraph.fillArc((int) (circle.getX() * 6.4)
                                        - radius / 2, circle.getY() * 4
                                        - radius / 2, radius, radius, 0, 360);
                            } else {
                                pGraph.drawArc((int) (circle.getX() * 6.4)
                                        - radius / 2, circle.getY() * 4
                                        - radius / 2, radius, radius, 0, 360);
                            }
                        } else if (path instanceof Arc) {
                            final Arc arc = (Arc) path;
                            final int x = (int) (arc.getLeft() * 6.4);
                            final int y = arc.getTop() * 4;
                            final int height = arc.getBottom() * 4 - y;
                            final int width = (int) (arc.getRight() * 6.4) - x;
                            if (arc.isFilled()) {
                                pGraph.fillArc(x, y, width, height, -arc
                                        .getStartAngle(), -arc.getSweepAngle());
                            } else {
                                pGraph.drawArc(x, y, width, height, -arc
                                        .getStartAngle(), -arc.getSweepAngle());
                            }
                        }
                    }
                }
            }
        }
    }

    public void refreshModel() {
        final DefaultTreeModel model = (DefaultTreeModel) this.tree.getModel();
        final DefaultMutableTreeNode root = (DefaultMutableTreeNode) model
                .getRoot();
        root.removeAllChildren();
        for (final Etape etape : this.modele.getEtapes()) {
            final DefaultMutableTreeNode nEtape = new DefaultMutableTreeNode(
                    etape);
            for (final IPath path : etape.getPaths()) {
                nEtape.add(new DefaultMutableTreeNode(path));
            }
            root.add(nEtape);
        }
        model.reload(root);
    }

    private void addEtape(final Etape etape) {
        this.modele.addEtape(etape);
        this.showEtapes.put(etape, Boolean.TRUE);
    }

    private void addPath(final Etape etape, final IPath path) {
        etape.addPath(path);
        this.showPaths.put(path, Boolean.TRUE);
    }

    public ActionListener addLine = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            System.out.println("Nouvelle ligne");
            final Object path = PanelDraw.this.tree.getSelected();
            Etape etape = null;
            if (path instanceof Dessin) {
                etape = new Etape();
                PanelDraw.this.draw = new Line();
                PanelDraw.this.addPath(etape, PanelDraw.this.draw);
                PanelDraw.this.addEtape(etape);
            } else if (path instanceof Etape) {
                etape = (Etape) path;
                PanelDraw.this.draw = new Line();
                PanelDraw.this.addPath(etape, PanelDraw.this.draw);
            }
            PanelDraw.this.refreshModel();
        }
    };

    public ActionListener addCircle = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            System.out.println("Nouveau cercle");
            final Object path = PanelDraw.this.tree.getSelected();
            Etape etape = null;
            if (path instanceof Dessin) {
                etape = new Etape();
                PanelDraw.this.draw = new Circle();
                PanelDraw.this.addPath(etape, PanelDraw.this.draw);
                PanelDraw.this.addEtape(etape);
            } else if (path instanceof Etape) {
                etape = (Etape) path;
                PanelDraw.this.draw = new Circle();
                PanelDraw.this.addPath(etape, PanelDraw.this.draw);
            }
            PanelDraw.this.refreshModel();
        }
    };

    public ActionListener addArc = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            System.out.println("Nouvel arc");
            final String start = JOptionPane
                    .showInputDialog("Angle de départ : ");
            final String sweep = JOptionPane.showInputDialog("Angle : ");
            final Object path = PanelDraw.this.tree.getSelected();
            Etape etape = null;
            if (path instanceof Dessin) {
                etape = new Etape();
                PanelDraw.this.draw = new Arc();
                final Arc arc = (Arc) PanelDraw.this.draw;
                arc.setStartAngle(Integer.parseInt(start));
                arc.setSweepAngle(Integer.parseInt(sweep));
                PanelDraw.this.addPath(etape, arc);
                PanelDraw.this.addEtape(etape);
            } else if (path instanceof Etape) {
                etape = (Etape) path;
                PanelDraw.this.draw = new Arc();
                final Arc arc = (Arc) PanelDraw.this.draw;
                arc.setStartAngle(Integer.parseInt(start));
                arc.setSweepAngle(Integer.parseInt(sweep));
                PanelDraw.this.addPath(etape, arc);
            }
            PanelDraw.this.refreshModel();
        }
    };

    public ActionListener editer = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            final Object obj = PanelDraw.this.tree.getSelected();
            final JDialog dialog = new JDialog();
            dialog.setModal(true);
            dialog.setSize(400, 300);
            final JPanel panel = new JPanel();
            final Dimension dimText = new Dimension(150, 30);
            panel.add(new JLabel("show: "));
            final JCheckBox cShow = new JCheckBox();
            cShow.setSelected(true);
            cShow.addChangeListener(new ChangeListener() {

                @Override
                public void stateChanged(final ChangeEvent pEvent) {
                    final Object select = PanelDraw.this.tree.getSelected();
                    final JCheckBox source = (JCheckBox) pEvent.getSource();
                    if (select instanceof Etape) {
                        PanelDraw.this.showEtapes.put((Etape) select, source
                                .isSelected());
                    } else if (select instanceof IPath) {
                        PanelDraw.this.showPaths.put((IPath) select, source
                                .isSelected());
                    }
                    PanelDraw.this.repaint();
                }
            });
            panel.add(cShow);
            if (obj instanceof Dessin) {
                System.out.println("Select DESSIN");
                panel.add(new JLabel("name: " + ((Dessin) obj).getName()));
            } else if (obj instanceof Etape) {
                System.out.println("Select ETAPE");
            } else if (obj instanceof Line) {
                System.out.println("Select LINE");
                final Line line = (Line) obj;
                final JTextField tX1 = new JTextField(String.valueOf(line
                        .getX1()));
                tX1.setPreferredSize(dimText);
                tX1.setName("x1");
                tX1.addKeyListener(PanelDraw.this.updateLine);
                final JTextField tY1 = new JTextField(String.valueOf(line
                        .getY1()));
                tY1.setPreferredSize(dimText);
                tY1.setName("y1");
                tY1.addKeyListener(PanelDraw.this.updateLine);
                final JTextField tX2 = new JTextField(String.valueOf(line
                        .getX2()));
                tX2.setPreferredSize(dimText);
                tX2.setName("x2");
                tX2.addKeyListener(PanelDraw.this.updateLine);
                final JTextField tY2 = new JTextField(String.valueOf(line
                        .getY2()));
                tY2.setPreferredSize(dimText);
                tY2.setName("y2");
                tY2.addKeyListener(PanelDraw.this.updateLine);
                panel.add(new JLabel("x1: "));
                panel.add(tX1);
                panel.add(new JLabel("y1: "));
                panel.add(tY1);
                panel.add(new JLabel("x2: "));
                panel.add(tX2);
                panel.add(new JLabel("y2: "));
                panel.add(tY2);
            } else if (obj instanceof Circle) {
                System.out.println("Select CIRCLE");
                final Circle circle = (Circle) obj;
                final JTextField tX = new JTextField(String.valueOf(circle
                        .getX()));
                tX.setPreferredSize(dimText);
                tX.setName("x");
                tX.addKeyListener(PanelDraw.this.updateCircle);
                final JTextField tY = new JTextField(String.valueOf(circle
                        .getY()));
                tY.setPreferredSize(dimText);
                tY.setName("y");
                tY.addKeyListener(PanelDraw.this.updateCircle);
                final JTextField tR = new JTextField(String.valueOf(circle
                        .getRadius()));
                tR.setPreferredSize(dimText);
                tR.setName("radius");
                tR.addKeyListener(PanelDraw.this.updateCircle);
                final JCheckBox cFill = new JCheckBox();
                cFill.addChangeListener(new ChangeListener() {

                    @Override
                    public void stateChanged(final ChangeEvent pEvent) {
                        final Circle circle = (Circle) PanelDraw.this.tree
                                .getSelected();
                        final JCheckBox source = (JCheckBox) pEvent.getSource();
                        circle.setFilled(source.isSelected());
                        PanelDraw.this.repaint();
                    }
                });
                panel.add(new JLabel("x: "));
                panel.add(tX);
                panel.add(new JLabel("y: "));
                panel.add(tY);
                panel.add(new JLabel("radius: "));
                panel.add(tR);
                panel.add(new JLabel("filled: "));
                panel.add(cFill);
            } else if (obj instanceof Arc) {
                System.out.println("Select ARC");
                final Arc arc = (Arc) obj;
                final JTextField tLeft = new JTextField(String.valueOf(arc
                        .getLeft()));
                tLeft.setPreferredSize(dimText);
                tLeft.setName("left");
                tLeft.addKeyListener(PanelDraw.this.updateArc);
                final JTextField tTop = new JTextField(String.valueOf(arc
                        .getTop()));
                tTop.setPreferredSize(dimText);
                tTop.setName("top");
                tTop.addKeyListener(PanelDraw.this.updateArc);
                final JTextField tRight = new JTextField(String.valueOf(arc
                        .getRight()));
                tRight.setPreferredSize(dimText);
                tRight.setName("right");
                tRight.addKeyListener(PanelDraw.this.updateArc);
                final JTextField tBottom = new JTextField(String.valueOf(arc
                        .getBottom()));
                tBottom.setPreferredSize(dimText);
                tBottom.setName("bottom");
                tBottom.addKeyListener(PanelDraw.this.updateArc);
                final JTextField tStart = new JTextField(String.valueOf(arc
                        .getStartAngle()));
                tStart.setPreferredSize(dimText);
                tStart.setName("startAngle");
                tStart.addKeyListener(PanelDraw.this.updateArc);
                final JTextField tSweep = new JTextField(String.valueOf(arc
                        .getSweepAngle()));
                tSweep.setPreferredSize(dimText);
                tSweep.setName("sweepAngle");
                tSweep.addKeyListener(PanelDraw.this.updateArc);
                final JCheckBox cFill = new JCheckBox();
                cFill.addChangeListener(new ChangeListener() {

                    @Override
                    public void stateChanged(final ChangeEvent pEvent) {
                        final Arc arc = (Arc) PanelDraw.this.tree.getSelected();
                        final JCheckBox source = (JCheckBox) pEvent.getSource();
                        arc.setFilled(source.isSelected());
                        PanelDraw.this.repaint();
                    }
                });
                panel.add(new JLabel("left: "));
                panel.add(tLeft);
                panel.add(new JLabel("top: "));
                panel.add(tTop);
                panel.add(new JLabel("right: "));
                panel.add(tRight);
                panel.add(new JLabel("bottom: "));
                panel.add(tBottom);
                panel.add(new JLabel("startAngle: "));
                panel.add(tStart);
                panel.add(new JLabel("sweepAngle: "));
                panel.add(tSweep);
                panel.add(new JLabel("filled: "));
                panel.add(cFill);
            }
            dialog.add(panel);
            dialog.setVisible(true);
        }
    };

    public KeyAdapter updateArc = new KeyAdapter() {

        @Override
        public void keyReleased(final KeyEvent pEvent) {
            final JTextField source = (JTextField) pEvent.getSource();
            final Arc arc = (Arc) PanelDraw.this.tree.getSelected();
            if ("left".equals(source.getName())) {
                arc.setLeft(Integer.parseInt(source.getText()));
            } else if ("top".equals(source.getName())) {
                arc.setTop(Integer.parseInt(source.getText()));
            } else if ("right".equals(source.getName())) {
                arc.setRight(Integer.parseInt(source.getText()));
            } else if ("bottom".equals(source.getName())) {
                arc.setBottom(Integer.parseInt(source.getText()));
            } else if ("startAngle".equals(source.getName())) {
                arc.setStartAngle(Integer.parseInt(source.getText()));
            } else if ("sweepAngle".equals(source.getName())) {
                arc.setSweepAngle(Integer.parseInt(source.getText()));
            }
            PanelDraw.this.repaint();
        }

    };

    public KeyAdapter updateLine = new KeyAdapter() {

        @Override
        public void keyReleased(final KeyEvent pEvent) {
            final JTextField source = (JTextField) pEvent.getSource();
            final Line line = (Line) PanelDraw.this.tree.getSelected();
            if ("x1".equals(source.getName())) {
                line.setX1(Integer.parseInt(source.getText()));
            } else if ("y1".equals(source.getName())) {
                line.setY1(Integer.parseInt(source.getText()));
            } else if ("x2".equals(source.getName())) {
                line.setX2(Integer.parseInt(source.getText()));
            } else if ("y2".equals(source.getName())) {
                line.setY2(Integer.parseInt(source.getText()));
            }
            PanelDraw.this.repaint();
        }

    };

    public KeyAdapter updateCircle = new KeyAdapter() {

        @Override
        public void keyReleased(final KeyEvent pEvent) {
            final JTextField source = (JTextField) pEvent.getSource();
            final Circle circle = (Circle) PanelDraw.this.tree.getSelected();
            if ("x".equals(source.getName())) {
                circle.setX(Integer.parseInt(source.getText()));
            } else if ("y".equals(source.getName())) {
                circle.setY(Integer.parseInt(source.getText()));
            } else if ("radius".equals(source.getName())) {
                circle.setRadius(Integer.parseInt(source.getText()));
            }
            PanelDraw.this.repaint();
        }

    };

    public ActionListener openJSON = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            final JFileChooser fChooser = new JFileChooser(".");
            if (fChooser.showOpenDialog(null) == JFileChooser.OPEN_DIALOG) {
                final File json = fChooser.getSelectedFile();
                try {
                    final InputStream in = new FileInputStream(json);
                    final JsonReader reader = Json.createReader(in);
                    PanelDraw.this.modele = new Dessin();
                    final JsonObject dessin = reader.readObject();
                    PanelDraw.this.modele.setName(dessin.getString("name"));
                    final JsonArray etapes = dessin.getJsonArray("etapes");
                    for (final JsonValue etape : etapes) {
                        if (etape.getValueType().equals(ValueType.OBJECT)) {
                            final JsonObject oEtape = (JsonObject) etape;
                            final Etape dEtape = new Etape();
                            final JsonArray paths = oEtape
                                    .getJsonArray("paths");
                            for (final JsonValue path : paths) {
                                if (path.getValueType()
                                        .equals(ValueType.OBJECT)) {
                                    final JsonObject oPath = (JsonObject) path;
                                    IPath dPath = null;
                                    final JsonObject line = oPath
                                            .getJsonObject("line");
                                    if (line != null) {
                                        dPath = new Line();
                                        ((Line) dPath).setX1(line.getInt("x1"));
                                        ((Line) dPath).setY1(line.getInt("y1"));
                                        ((Line) dPath).setX2(line.getInt("x2"));
                                        ((Line) dPath).setY2(line.getInt("y2"));
                                    }
                                    final JsonObject circle = oPath
                                            .getJsonObject("circle");
                                    if (circle != null) {
                                        dPath = new Circle();
                                        ((Circle) dPath).setX(circle
                                                .getInt("x"));
                                        ((Circle) dPath).setY(circle
                                                .getInt("y"));
                                        ((Circle) dPath).setRadius(circle
                                                .getInt("radius"));
                                        if (circle.containsKey("filled")) {
                                            ((Circle) dPath).setFilled(circle
                                                    .getInt("filled") == 1);
                                        }
                                    }
                                    final JsonObject arc = oPath
                                            .getJsonObject("arc");
                                    if (arc != null) {
                                        dPath = new Arc();
                                        ((Arc) dPath).setLeft(arc
                                                .getInt("left"));
                                        ((Arc) dPath).setTop(arc.getInt("top"));
                                        ((Arc) dPath).setRight(arc
                                                .getInt("right"));
                                        ((Arc) dPath).setBottom(arc
                                                .getInt("bottom"));
                                        ((Arc) dPath).setStartAngle(arc
                                                .getInt("startAngle"));
                                        ((Arc) dPath).setSweepAngle(arc
                                                .getInt("sweepAngle"));
                                        if (arc.containsKey("filled")) {
                                            ((Arc) dPath).setFilled(arc
                                                    .getInt("filled") == 1);
                                        }
                                    }
                                    dEtape.addPath(dPath);
                                    PanelDraw.this.showPaths.put(dPath,
                                            Boolean.TRUE);
                                }
                            }
                            PanelDraw.this.modele.addEtape(dEtape);
                            PanelDraw.this.showEtapes.put(dEtape, Boolean.TRUE);
                        }
                    }
                    reader.close();
                    in.close();
                } catch (final IOException exc) {
                    exc.printStackTrace();
                }
            }
            PanelDraw.this.refreshModel();
            PanelDraw.this.repaint();
        }
    };

    public ActionListener exporter = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            try {
                final String name = JOptionPane
                        .showInputDialog("Nom du modele :");
                System.out.println("Export format JSON");

                final JsonObjectBuilder dessinBuilder = Json
                        .createObjectBuilder();
                dessinBuilder.add("name", name);
                final JsonArrayBuilder etapesBuilder = Json
                        .createArrayBuilder();
                for (final Etape etape : PanelDraw.this.modele.getEtapes()) {
                    final JsonObjectBuilder etapeBuilder = Json
                            .createObjectBuilder();
                    final JsonArrayBuilder pathsBuilder = Json
                            .createArrayBuilder();
                    for (final IPath path : etape.getPaths()) {
                        final JsonObjectBuilder pathBuilder = Json
                                .createObjectBuilder();
                        if (path instanceof Line) {
                            final Line line = (Line) path;
                            final JsonObjectBuilder lineBuilder = Json
                                    .createObjectBuilder();
                            lineBuilder.add("x1", line.getX1());
                            lineBuilder.add("y1", line.getY1());
                            lineBuilder.add("x2", line.getX2());
                            lineBuilder.add("y2", line.getY2());
                            pathBuilder.add("line", lineBuilder);
                        } else if (path instanceof Circle) {
                            final Circle circle = (Circle) path;
                            final JsonObjectBuilder circleBuilder = Json
                                    .createObjectBuilder();
                            circleBuilder.add("x", circle.getX());
                            circleBuilder.add("y", circle.getY());
                            circleBuilder.add("radius", circle.getRadius());
                            if (circle.isFilled()) {
                                circleBuilder.add("filled", 1);
                            } else {
                                circleBuilder.add("filled", 0);
                            }
                            pathBuilder.add("circle", circleBuilder);
                        } else if (path instanceof Arc) {
                            final Arc arc = (Arc) path;
                            final JsonObjectBuilder arcBuilder = Json
                                    .createObjectBuilder();
                            arcBuilder.add("left", arc.getLeft());
                            arcBuilder.add("top", arc.getTop());
                            arcBuilder.add("right", arc.getRight());
                            arcBuilder.add("bottom", arc.getBottom());
                            arcBuilder.add("startAngle", arc.getStartAngle());
                            arcBuilder.add("sweepAngle", arc.getSweepAngle());
                            if (arc.isFilled()) {
                                arcBuilder.add("filled", 1);
                            } else {
                                arcBuilder.add("filled", 0);
                            }
                            pathBuilder.add("arc", arcBuilder);
                        }
                        pathsBuilder.add(pathBuilder);
                    }
                    etapeBuilder.add("paths", pathsBuilder);
                    etapesBuilder.add(etapeBuilder);
                }
                dessinBuilder.add("etapes", etapesBuilder);

                final JsonObject empJsonObject = dessinBuilder.build();

                final OutputStream os = new FileOutputStream(name + ".json");
                final JsonWriter jsonWriter = Json.createWriter(os);
                jsonWriter.writeObject(empJsonObject);
                jsonWriter.close();
            } catch (final IOException exc) {
                // TODO Auto-generated catch block
                exc.printStackTrace();
            }
            System.out.println("JSON - END");
        }
    };

    public ActionListener deleteEtape = new ActionListener() {

        @Override
        public void actionPerformed(final ActionEvent pEvent) {
            final Object select = PanelDraw.this.tree.getSelected();
            if (select instanceof Etape) {
                PanelDraw.this.modele.getEtapes().remove(select);
            } else if (select instanceof IPath) {
                Etape eSelect = null;
                for (final Etape etape : PanelDraw.this.modele.getEtapes()) {
                    for (final IPath path : etape.getPaths()) {
                        if (path.equals(select)) {
                            eSelect = etape;
                            break;
                        }
                    }
                    if (eSelect != null) {
                        break;
                    }
                }
                if (eSelect != null) {
                    eSelect.getPaths().remove(select);
                }
            }
            PanelDraw.this.refreshModel();
            PanelDraw.this.repaint();
        }
    };

}
